package model;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Observable;

import xl.Address;
import xl.Environment;
import xl.XLException;

public class Sheet extends Observable implements Environment {
	private Map<Address, Cell> sheet;
	CellFactory factory = new CellFactory();

	public Sheet() {
		sheet = new HashMap<Address, Cell>();
		this.factory = new CellFactory();
	}
	
	public Sheet(Map<Address, Cell> map) {
		sheet = map;
		this.factory = new CellFactory();
	}

	public void replaceSheet(Map<Address, Cell> replacementSheet) {
		sheet = replacementSheet;
		lookForErrors();
		updateEverything();
	}
	
	public void lookForErrors() {
		Iterator<Address> itr = sheet.keySet().iterator();
		while (itr.hasNext()) {
			Address adr = (Address)itr.next();
			put(adr, sheet.get(adr).toString());
		}
	}

	public void put(Address key, String value) {
		if (value.length() > 0) {
			Cell oldCell = sheet.get(key);
			Cell newCell = null;
			sheet.put(key, new CircularErrorCell());
			try {
				newCell = factory.build(value);
				newCell.value(this);
				sheet.put(key, newCell);
			} catch (XLException e) {
				sheet.put(key, oldCell);
				throw new XLException(e.getMessage());
			}
		} else {
			sheet.remove(key);
		}
	}
	
	
	public double value(Object key) {
		return sheet.get(key).value(this);
	}

	public Cell getCell(Object key) {
		return sheet.get(key);
	}

	public Map<Address, Cell> getMap() {
		return sheet;
	}

	public String getParsedCell(Address address) {
		return getCell(address).parse(this);
	}

	public void updateEverything() {
		setChanged();
		notifyObservers(sheet);
	}
}
